from typing import Optional, List, Dict, Any, Union
from pydantic import BaseModel, Field, field_validator, FieldValidationInfo
from datetime import datetime
from .base import BaseSchema

# 子区域模型 - 适配DJI API的sub_areas结构
class NoFlySubArea(BaseModel):
    """禁飞区子区域模型"""
    # 圆形子区域属性
    lat: Optional[float] = Field(None, description="圆心纬度")
    lng: Optional[float] = Field(None, description="圆心经度")
    radius: Optional[float] = Field(None, ge=1, description="半径（米）")
    
    # 多边形子区域属性
    polygon_points: Optional[List[List[float]]] = Field(None, description="多边形坐标点，格式：[[lng1, lat1], [lng2, lat2], ...]")
    
    # 通用属性
    color: str = Field("#FF0000", description="显示颜色")
    level: str = Field("default", description="禁飞区级别")
    height: Optional[str] = Field(None, description="高度描述")

class NoFlyZoneBase(BaseSchema):
    """禁飞区基础模型 - 适配DJI API数据结构"""
    name: str = Field(..., max_length=100, description="禁飞区名称")
    description: Optional[str] = Field(None, max_length=255, description="描述")
    
    # 区域基本属性
    zone_type: str = Field("polygon", description="禁飞区类型", pattern="^(polygon|circle)$")
    level: str = Field("default", description="禁飞区级别")
    color: str = Field("#FF0000", description="显示颜色")
    
    # 圆形禁飞区属性
    lat: Optional[float] = Field(None, description="圆心纬度")
    lng: Optional[float] = Field(None, description="圆心经度")
    radius: Optional[float] = Field(None, ge=1, description="半径（米）")
    
    # 多边形禁飞区属性
    polygon_points: Optional[List[List[float]]] = Field(None, description="多边形坐标点，格式：[[lng1, lat1], [lng2, lat2], ...]")
    
    # 高度信息
    height: Optional[str] = Field(None, description="高度描述")
    min_altitude: float = Field(0.0, ge=0, description="最小高度（米）")
    max_altitude: float = Field(1000.0, ge=0, description="最大高度（米）")
    
    # 子区域信息 - 适配DJI API的sub_areas结构
    sub_areas: Optional[List[NoFlySubArea]] = Field(None, description="子区域列表")
    
    # 生效时间范围
    start_time: Optional[datetime] = Field(None, description="生效开始时间")
    end_time: Optional[datetime] = Field(None, description="生效结束时间")
    
    @field_validator('polygon_points')
    def validate_polygon_points(cls, v, info: FieldValidationInfo):
        """验证多边形类型的坐标不为空"""
        if info.data.get('zone_type') == 'polygon' and not v:
            raise ValueError("多边形类型的禁飞区必须提供坐标")
        if v:
            # 验证坐标格式是否正确
            if not isinstance(v, list):
                raise ValueError("polygon_points必须是列表")
            for point in v:
                if not isinstance(point, list) or len(point) != 2:
                    raise ValueError("坐标点必须是包含两个数字的列表 [lng, lat]")
                if not all(isinstance(coord, (int, float)) for coord in point):
                    raise ValueError("坐标值必须是数字")
        return v
    
    @field_validator('lat', 'lng', 'radius')
    def validate_circle_properties(cls, v, info: FieldValidationInfo):
        """验证圆形类型的属性不为空"""
        if info.data.get('zone_type') == 'circle':
            field_name = info.field_name
            if field_name == 'lat' and v is None:
                raise ValueError("圆形类型的禁飞区必须提供圆心纬度")
            if field_name == 'lng' and v is None:
                raise ValueError("圆形类型的禁飞区必须提供圆心经度")
            if field_name == 'radius' and v is None:
                raise ValueError("圆形类型的禁飞区必须提供半径")
        return v
    
    @field_validator('max_altitude')
    def validate_max_altitude(cls, v, info: FieldValidationInfo):
        """验证最大高度大于等于最小高度"""
        if v < info.data.get('min_altitude', 0):
            raise ValueError("最大高度必须大于等于最小高度")
        return v
    
    @field_validator('end_time')
    def validate_time_range(cls, v, info: FieldValidationInfo):
        """验证结束时间大于开始时间"""
        if info.data.get('start_time') and v and v <= info.data['start_time']:
            raise ValueError("结束时间必须大于开始时间")
        return v

class NoFlyZoneCreate(NoFlyZoneBase):
    """创建禁飞区模型"""
    pass

class NoFlyZoneUpdate(NoFlyZoneBase):
    """更新禁飞区模型"""
    name: Optional[str] = Field(None, max_length=100, description="禁飞区名称")
    zone_type: Optional[str] = Field(None, description="禁飞区类型", pattern="^(polygon|circle)$")
    level: Optional[str] = Field(None, description="禁飞区级别")
    color: Optional[str] = Field(None, description="显示颜色")

class NoFlyZoneSchema(NoFlyZoneBase):
    """禁飞区响应模型"""
    id: int = Field(..., description="ID")
    created_at: datetime = Field(..., description="创建时间")
    updated_at: datetime = Field(..., description="更新时间")

# 适配DJI API的响应数据结构
class DJINoFlyZoneResponse(BaseModel):
    """DJI风格的禁飞区响应结构"""
    code: int = Field(0, description="状态码")
    message: Dict[str, str] = Field(default={"chinese": "成功", "english": "OK"}, description="消息")
    data: Dict[str, Any] = Field(..., description="响应数据")
    
    @classmethod
    def from_no_fly_zones(cls, no_fly_zones: List[NoFlyZoneSchema]):
        """从禁飞区列表创建DJI风格的响应"""
        # 转换为DJI API兼容的数据格式
        areas = []
        for zone in no_fly_zones:
            area = {
                "name": zone.name,
                "color": zone.color,
                "level": zone.level,
                "height": zone.height or f"{zone.min_altitude}m-{zone.max_altitude}m"
            }
            
            # 根据类型添加相应的几何信息
            if zone.zone_type == "circle" and zone.lat and zone.lng and zone.radius:
                area.update({
                    "lat": zone.lat,
                    "lng": zone.lng,
                    "radius": zone.radius
                })
            elif zone.zone_type == "polygon" and zone.polygon_points:
                area.update({
                    "polygon_points": zone.polygon_points
                })
            
            # 添加子区域信息
            if zone.sub_areas:
                area["sub_areas"] = [sub.dict() for sub in zone.sub_areas]
            
            areas.append(area)
        
        return cls(
            code=0,
            message={"chinese": "成功", "english": "OK"},
            data={
                "areas": areas,
                "country": "",  # 可根据实际情况填充
                "lat": 0,  # 可根据实际情况填充
                "lng": 0  # 可根据实际情况填充
            }
        )